package com.xx.redBook.service.impl;

import cn.hutool.crypto.SecureUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.http.Method;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.xx.common.tools.IpPools.RespIPs;
import com.xx.common.utils.DateUtils;
import com.xx.common.utils.SecurityUtils;
import com.xx.common.utils.StringUtils;
import com.xx.redBook.domain.RedBookAccount;
import com.xx.redBook.domain.RedBookLike;
import com.xx.redBook.domain.RedBookLikeRecord;
import com.xx.redBook.domain.model.RedBookResponse;
import com.xx.redBook.domain.vo.RedBookBatchLikeVO;
import com.xx.redBook.domain.vo.RedBookResponseVO;
import com.xx.redBook.mapper.RedBookAccountMapper;
import com.xx.redBook.mapper.RedBookLikeMapper;
import com.xx.redBook.mapper.RedBookLikeRecordMapper;
import com.xx.redBook.service.IRedBookLikeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 哔哩账号Service业务层处理
 *
 * @author ruoyi
 * @date 2024-09-28
 */
@Service
public class RedBookLikeServiceImpl implements IRedBookLikeService {

    @Value("${ipPool.url}")
    private String ipPoolUrl;

    @Value("${ipPool.key}")
    private String ipPoolKey;

    @Value("${ipPool.orderNum}")
    private String ipPoolOrderNum;

    @Autowired
    private RedBookLikeMapper biLiLikeMapper;

    @Autowired
    private RedBookLikeRecordMapper biLiLikeRecordMapper;

    @Autowired
    private RedBookAccountMapper biLiAccountMapper;

    /**
     * 查询哔哩点赞
     *
     * @param id 哔哩点赞主键
     * @return 哔哩点赞
     */
    @Override
    public RedBookLike selectRedBookLikeById(String id) {
        return biLiLikeMapper.selectRedBookLikeById(id);
    }

    /**
     * 查询哔哩点赞列表
     *
     * @param biLiLike 哔哩点赞
     * @return 哔哩点赞
     */
    @Override
    public List<RedBookLike> selectRedBookLikeList(RedBookLike biLiLike) {
        biLiLike.setCreateBy(SecurityUtils.getUserId().toString());
        return biLiLikeMapper.selectRedBookLikeList(biLiLike);
    }

    /**
     * 新增哔哩点赞
     *
     * @param biLiLike 哔哩点赞
     * @return 结果
     */
    @Override
    public List<String> insertRedBookLike(RedBookLike biLiLike) {

        if(StringUtils.isEmpty(biLiLike.getId())){
            biLiLike.setId(UUID.randomUUID().toString().replaceAll("-", ""));
            biLiLike.setCreateTime(DateUtils.getNowDate());
            biLiLike.setCreateBy(SecurityUtils.getUserId().toString());
            biLiLikeMapper.insertRedBookLike(biLiLike);
        }

        String url = "";
        if ("点赞".equals(biLiLike.getHandleType())) {
            url = "https://api.bilibili.com/x/v2/reply/action"; // 点赞
        } else if ("点踩".equals(biLiLike.getHandleType())) {
            url = "https://api.bilibili.com/x/v2/reply/hate"; // 点踩
        }

        // 直接查询未点赞的用户，一步到位
        List<RedBookAccount> unlikedAccounts = biLiAccountMapper.selectUnlikedAccounts(
                biLiLike.getOid(),
                biLiLike.getRpid(),
                SecurityUtils.getUserId().toString(),
                biLiLike.getCount()
        );

//        // 查询当前账号的账号列表
//        RedBookAccount bl = new RedBookAccount();
//        bl.setCreateBy(SecurityUtils.getUserId().toString());
//        List<RedBookAccount> list = biLiAccountMapper.selectRedBookAccountList(bl);
//
//        // 查询到当前链接已经点赞【成功】的用户，并排除用户
//        RedBookLikeRecord param = new RedBookLikeRecord();
//        param.setOid(biLiLike.getOid());
//        param.setRpid(biLiLike.getRpid());
//        param.setHandleType(biLiLike.getHandleType());
//        param.setMessage("成功");
//        List<RedBookLikeRecord> biLiLikeRecords = biLiLikeRecordMapper.selectRedBookLikeRecordList(param);
//
//        // 获取已经点赞的accountId集合
//        Set<String> likedAccountIds = biLiLikeRecords.stream()
//                .map(RedBookLikeRecord::getAccountId)
//                .collect(Collectors.toSet());
//
//        // 过滤出未点赞的账号
//        List<RedBookAccount> unlikedAccounts = list.stream()
//                .filter(account -> !likedAccountIds.contains(account.getId()))
//                .collect(Collectors.toList());

        // 打乱列表顺序，保证每个账号都有点赞的机会
        Collections.shuffle(unlikedAccounts);

        // 计算实际需要使用的账号数量
        int actualCount = Math.min(unlikedAccounts.size(), biLiLike.getCount());

        // 获取需要的账号子列表（避免修改原列表）
        List<RedBookAccount> newList = unlikedAccounts.subList(0, actualCount);

        int LikeSuccessCount = 0;

        // 获取ip
//        String ipProxy = getIpProxy();
//        String[] split = ipProxy.split(":");
//        String proxyHost = split[0];
//        String proxyPort = split[1];

        Random random = new Random();

        for (RedBookAccount biLiAccount : newList) {

            // 每次点赞，加入随机延迟，50-100毫秒
            try {
                int time = 50 + random.nextInt(101);
                System.out.println("点赞序列，待机：" + time + "毫秒");
                Thread.sleep(time);
            } catch (Exception e) {
                throw new RuntimeException("待机异常：" + e);
            }

            HashMap<String, Object> paramMap = new HashMap<>();
            paramMap.put("oid", biLiLike.getOid());
            paramMap.put("rpid", biLiLike.getRpid());
            paramMap.put("type", "1");
            paramMap.put("action", "1");

            // 提取加密参数
            String cookie = biLiAccount.getCookie();
            Matcher matcher = Pattern.compile("bili_jct=([^;]+)").matcher(cookie);
            if (matcher.find()) {
                paramMap.put("csrf", matcher.group(1));
            } else {
                System.out.println("bili_jct not found");
            }
            paramMap.put("statistics", "{\"appId\":100,\"platform\":5}");
            // 设置请求头
            Map<String, String> headers = new HashMap<>();
            headers.put("Cookie", cookie);

            // 发送POST请求
            String result = HttpUtil.createPost(url).headerMap(headers, true)
//                    .setHttpProxy(proxyHost, Integer.parseInt(proxyPort)) // 设置ip代理
                    .form(paramMap).execute().body();
            JSONObject json = new JSONObject(result);
            int code = json.getInt("code");

            // 封装记录数据
            RedBookLikeRecord biLiLikeRecord = new RedBookLikeRecord();
            biLiLikeRecord.setOid(biLiLike.getOid());
            biLiLikeRecord.setRpid(biLiLike.getRpid());
            biLiLikeRecord.setAccountId(biLiAccount.getId());
            biLiLikeRecord.setLikeId(biLiLike.getId());

            if (code == 0) {
                biLiLikeRecord.setMessage(biLiLike.getHandleType() + "成功");
                // 更新用户点赞次数
                biLiAccount.setCount(biLiAccount.getCount() + 1);
                biLiAccount.setEndTime(DateUtils.getNowDate());
                biLiAccountMapper.updateRedBookAccount(biLiAccount);

                // 点赞成功
                LikeSuccessCount++;
            } else {
                // 如果包含 request was banned 则出发了风控条件
                if(json.getStr("message").contains("request was banned")){
                    throw new RuntimeException("点赞频繁，请过一段时间在来");
                }
                biLiLikeRecord.setMessage(biLiLike.getHandleType() + "失败，失败原因：" + json.getStr("message"));
            }
            // 保存点赞记录
            biLiLikeRecord.setId(UUID.randomUUID().toString().replaceAll("-", ""));
            biLiLikeRecord.setCode(code);
            biLiLikeRecord.setHandleType(biLiLike.getHandleType());
            biLiLikeRecord.setCreateTime(DateUtils.getNowDate());
            biLiLikeRecordMapper.insertRedBookLikeRecord(biLiLikeRecord);
        }

        // 下单数量
        Integer count = biLiLike.getCount();

        if(count - LikeSuccessCount > 0){
            biLiLike.setCount(biLiLike.getCount() - LikeSuccessCount);
            insertRedBookLike(biLiLike);
        }

        return null;
    }

    /**
     * 修改哔哩点赞
     *
     * @param biLiLike 哔哩点赞
     * @return 结果
     */
    @Override
    public int updateRedBookLike(RedBookLike biLiLike) {
        return biLiLikeMapper.updateRedBookLike(biLiLike);
    }

    /**
     * 批量删除哔哩点赞
     *
     * @param ids 需要删除的哔哩点赞主键
     * @return 结果
     */
    @Override
    public int deleteRedBookLikeByIds(String[] ids) {

        for (String biliLikeId : ids) {
            // 先查询所有的
            RedBookLike biLiLike = biLiLikeMapper.selectRedBookLikeById(biliLikeId);
            biLiLikeMapper.deleteRedBookLikeById(biliLikeId);

            // 同时删除对应的点赞记录数据
            List<RedBookLike> biLiLikes = biLiLikeMapper.selectRedBookLikeList(biLiLike);
            if(biLiLikes.isEmpty()){
                biLiLikeRecordMapper.deleteByRedBookLikeOidAndRpid(biLiLike.getOid(), biLiLike.getRpid());
            }
        }
        return 1;
    }

    @Override
    public Map<String, Object> checkOidRpidLikeCount(RedBookLike biLiLike) {

        if (biLiLike.getOid() == null || biLiLike.getRpid() == null || biLiLike.getHandleType() == null) {
            throw new IllegalArgumentException("关键参数不能为空【oid】【rpid】【下单类型】");
        }
        return biLiLikeRecordMapper.checkLikeAccountList(biLiLike.getOid(), biLiLike.getRpid(), biLiLike.getHandleType());
    }

    @Override
    public void batchRedBookLike(RedBookBatchLikeVO redBookBatchLikeVO) {

        // 1. 参数校验
        if (redBookBatchLikeVO.getReplies() == null || redBookBatchLikeVO.getReplies().isEmpty()) {
            throw new RuntimeException("评论列表不能为空");
        }

        if(redBookBatchLikeVO.getQuantity() > 0){
            Integer totalQuantity = redBookBatchLikeVO.getQuantity();
            List<RedBookResponseVO> replies = redBookBatchLikeVO.getReplies();
            int replyCount = replies.size();
            // 计算基础值和浮动范围
            int baseValue = totalQuantity / replyCount;
            int floatRange = (int) Math.round(baseValue * 0.5); // 20%浮动范围
            // 分配数量
            int remaining = totalQuantity;
            Random random = new Random();
            for (int i = 0; i < replyCount; i++) {
                RedBookResponseVO reply = replies.get(i);
                if (i == replyCount - 1) {
                    // 最后一条取剩余数量
                    reply.setCount(remaining);
                } else {
                    // 计算当前条的可分配范围
                    int min = Math.max(1, baseValue - floatRange);
                    int max = Math.min(baseValue + floatRange, remaining);
                    // 随机分配数量（保证至少分配1）
                    int allocated = min + random.nextInt(max - min + 1);
                    allocated = Math.min(allocated, remaining - (replyCount - i - 1)); // 确保剩余足够分配
                    reply.setCount(allocated);
                    remaining -= allocated;
                }
            }
        }


        for (RedBookResponseVO reply : redBookBatchLikeVO.getReplies()) {
            RedBookLike biLiLike = new RedBookLike();
            biLiLike.setOid(reply.getOid());
            biLiLike.setRpid(reply.getRpid());
            biLiLike.setHandleType(redBookBatchLikeVO.getHandleType());
            biLiLike.setCount(reply.getCount());
            insertRedBookLike(biLiLike);
        }

    }

    @Override
    public List<RedBookResponse> getReplyByMainUrl(String url) {

        // 获取用户列表
        List<RedBookAccount> accountList = biLiAccountMapper.selectRedBookAccountList(null);

        JSONObject json = null;
        boolean flag = false;
        String result = "";

        // 遍历用户列表获取Cookie直到得到一个可用的
        for (RedBookAccount biLiAccount : accountList) {
            // 设置请求头
            Map<String, String> headers = new HashMap<>();
            headers.put("Cookie", biLiAccount.getCookie());
            result = HttpUtil.createGet(url).headerMap(headers, true).execute().body();
            json = new JSONObject(result);
            int code = json.getInt("code");
            if (code == 0) {
                flag = true;
                break;
            }
        }
        if (!flag) {
            throw new RuntimeException("没有可用的在线账号");
        }


        JSONObject data = json.getJSONObject("data");
        JSONArray replies = data.getJSONArray("replies");

        System.out.println(replies);

        List<RedBookResponse> redBookResponseList = new ArrayList<>();

        try {
            for (int i = 0; i < replies.size(); i++) {
                JSONObject reply = replies.getJSONObject(i);
                long rpid = reply.getLong("rpid");
                long oid = reply.getLong("oid");
                ObjectMapper mapper = new ObjectMapper();
                JsonNode root = mapper.readTree(result);
                String uname = root.path("data").path("replies").get(i).path("member").path("uname").asText();
                String message = root.path("data").path("replies").get(i).path("content").path("message").asText();
                redBookResponseList.add(new RedBookResponse(oid, rpid, uname, message));
            }
        } catch (JsonProcessingException e) {
            System.out.println("报错了");
            throw new RuntimeException(e);
        }

        System.out.println(redBookResponseList);
        return redBookResponseList;
    }

    private String getIpProxy(){

        String sign = "num=" + 1
                + "&result_type=json" //返回格式
                + "&trade_no=" + ipPoolOrderNum // 订单号 包时 9.6-1w
                + "&key=" + ipPoolKey;
        sign = sign + "&sign=" + SecureUtil.md5(sign);

        // 调用接口获取动态ip
        String getIpURL = ipPoolUrl + sign;
        cn.hutool.http.HttpResponse responseIps = HttpUtil.createRequest(Method.POST, getIpURL).timeout(5000).execute();

        RespIPs respIPs = JSONUtil.toBean(responseIps.body(), RespIPs.class);
        if("400".equals(respIPs.getCode())){
            throw new RuntimeException(respIPs.getMsg());
        }
        String ip = respIPs.getData().getProxy_list().get(0);

        return ip;
    }

}
